#ifndef TRANSMATCH_H
#define TRANSMATCH_H

#include <QString>
#include <QVector>
#include <QPair>

#include "transaction.h"
#include "transseries.h"
#include "TransPlotHelper.h"

class TransMatch {
public:
    typedef QVector<QPair<const Transaction*, const Transaction*> > TransMatchVector;
    typedef QPair<const Transaction*, const Transaction*>  TransMatchPair;

    virtual bool match(const Transaction& trans1, const Transaction& trans2) = 0;
    virtual void getConnections(const TransSeries &master, const TransSeries &slave, TransMatchVector& connections) = 0;

protected:
    bool compareColum(const Transaction& trans1, const Transaction& trans2, const QString& columName) {
        bool OK1 = false;
        bool OK2 = false;
        QString str1, str2;
        str1 = trans1.findValueByColumName(columName, OK1);
        str2 = trans2.findValueByColumName(columName, OK2);
        if (! (OK1 && OK2 && (str1 == str2)) ) {
            return false;
        }
        return true;
    }
};

class JCBMatch : public TransMatch {
public:

    // JCB Match : ID, ADDR, and CMD
    virtual bool match(const Transaction &trans1, const Transaction &trans2) {
        bool id_mactch = compareColum(trans1, trans2, "ID");
        bool descAddr  = compareColum(trans1, trans2, "DescAddr");
        bool addr      = compareColum(trans1, trans2, "ADDR");

        if (id_mactch && descAddr && addr) {
            return true;
        }
        return false;
    }

    virtual void getConnections(const TransSeries &master, const TransSeries &slave, TransMatchVector& connections) {
        QVector<const Transaction*> scannedSlaves;

        // Walk throught the master
        TransSeries::TypeTransVector::ConstIterator iter_m = master.getSeries().constBegin();

        while (iter_m != master.getSeries().constEnd()) {
            const Transaction& tran1 = *iter_m;
            const Transaction* pTrans1 = iter_m;

            TransSeries::TypeTransVector::ConstIterator iter_s = slave.getSeries().constBegin();
            int begin = TransPlotHelper::getSeriesPosByTime(slave, iter_m->getTime());
            iter_s += begin;

            // Then walk through the slave
            while( iter_s != slave.getSeries().constEnd() ) {
                const Transaction& tran2 = *iter_s;
                const Transaction* pTrans2 = iter_s;
                if ( match(tran1, tran2) ) {
                    // If match, record the result in "connections"
                    // and put slave in the scannedSlaves
                    if (scannedSlaves.contains(iter_s)) {
                        // If this slave is already used, then still needs to find next match.
                    }
                    else {
                        scannedSlaves.append(pTrans2);

                        TransMatchPair pair(pTrans1, pTrans2);
                        connections.append(pair);
                        break;
                    }
                }
                iter_s++;
            }

            iter_m++;
        }

    }
};

#endif
